共计 7686 个字符,预计需要花费 20 分钟才能阅读完成。
背景
近期有业务部门需要在 k8s 环境中使用 nvidia GPU运行 cuda 环境。需要在操作系统中安装好驱动,制作 k8s GPU 镜像。
操作步骤
操作系统:Ubuntu 20.04
内核版本:5.15.0-76-generic
CPU 架构:X86_64
显卡型号:NVIDIA T4
参考链接:nvidia Linux 安装指南
前置准备
在 Linux 上安装 CUDA 工具包和驱动程序之前,必须执行一些操作:
- 验证系统是否具有支持 CUDA 的 GPU。
- 验证系统正在运行受支持的 Linux 版本。
- 验证系统是否已安装 gcc。
兼容性确认
验证系统是否具有支持 CUDA 的 GPU
# lspci | grep -i nvidia
00:0d.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
验证系统正在运行受支持的 Linux 版本
确认CPU 架构和内核版本是否受支持
验证系统是否已安装 gcc
# gcc --version
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
若未安装,则执行安装 gcc 和 make:
apt-get install gcc make
关闭自动更新
将 /etc/apt/apt.conf.d/10periodic
配置项的值改为 0
:
# 查看当前配置
# cat /etc/apt/apt.conf.d/10periodic
APT::Periodic::Update-Package-Lists "1"; # 自动更新频率,单位为day
APT::Periodic::Download-Upgradeable-Packages "0"; # 是否自动下载可升级的软件包
APT::Periodic::AutocleanInterval "0"; # 自动清理过期软件包的时间间隔
# 将配置项中的 1 变为 0,并创建备份文件
sed -i.bak 's/1/0/' /etc/apt/apt.conf.d/10periodic
避免自动更新时更新内核,需要将 /etc/apt/apt.conf.d/50unattended-upgrades
中配置项 "linux-image-*";
、"linux-headers-*";
注释掉:
vim /etc/apt/apt.conf.d/50unattended-upgrades
...
Unattended-Upgrade::Package-Blacklist {
# "linux-image-*";
# "linux-headers-*";
...
};
...
关闭 Nouveau 驱动程序
如果以下命令打印任何内容,则加载 Nouveau 驱动程序:
# lsmod | grep nouveau
nouveau 2285568 0
mxm_wmi 16384 1 nouveau
i2c_algo_bit 16384 1 nouveau
drm_ttm_helper 16384 1 nouveau
ttm 86016 2 drm_ttm_helper,nouveau
drm_kms_helper 307200 4 cirrus,nouveau
video 61440 1 nouveau
drm 618496 6 drm_kms_helper,cirrus,drm_ttm_helper,ttm,nouveau
wmi 32768 2 mxm_wmi,nouveau
关闭驱动:
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist-nvidia-nouveau.conf
echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nvidia-nouveau.conf
update-initramfs -u
reboot
安装显卡驱动
安装显卡驱动有两种方式:
- apt-get 包管理器安装
- 运行文件安装
apt 包管理器方式
使用 apt 包管理器安装 NVIDIA 驱动时,DKMS (Dynamic Kernel Module Support) 会在系统内核更新时自动更新驱动。
在生产环境中,我们往往不期望这种耦合的自动更新策略,当新驱动未生效时可能导致故障定位花费大量时间。
运行文件安装
官网上搜索对应版本的驱动链接:驱动检索
创建下载任务后,复制出下载链接,在服务器上执行下载和安装
# 下载
wget https://us.download.nvidia.cn/tesla/535.129.03/NVIDIA-Linux-x86_64-535.129.03.run
chmod +x NVIDIA-Linux-x86_64-535.129.03.run
# 执行安装,会进入到交互界面,出现选项连续回车即可
./NVIDIA-Linux-x86_64-535.129.03.run
# 确认驱动是否正确安装
# nvidia-smi
Thu Nov 9 17:47:49 2023
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 Tesla T4 Off | 00000000:00:0D.0 Off | 0 |
| N/A 55C P0 27W / 70W | 2MiB / 15360MiB | 7% Default |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| No running processes found |
+---------------------------------------------------------------------------------------+
驱动持久化
nvidia-persistenced --persistence-mode
命令用于启用 NVIDIA 持久模式(Persistence Mode)。
NVIDIA 持久模式是一种特殊模式,它允许 NVIDIA 驱动在系统启动时持续运行,即使没有活动的 X 服务器会话。通常情况下,NVIDIA 驱动只在 X 服务器会话或其他图形环境中加载和运行。当所有图形环境关闭时,驱动会自动卸载。
通过启用持久模式,你可以确保 NVIDIA 驱动在没有活动 X 服务器会话的情况下仍然保持加载和运行状态。这对于需要在无人值守服务器或没有图形界面的系统上运行 NVIDIA 驱动的应用程序很有用,如 CUDA 加速计算、深度学习训练等。
nvidia-persistenced --persistence-mode
命令会启动一个后台进程,该进程负责维护 NVIDIA 驱动的持久模式。你可以将此命令添加到系统启动脚本中,以确保在系统启动时自动启用持久模式。
nvidia-persistenced --persistence-mode
cd /usr/share/doc/NVIDIA_GLX-1.0/samples
tar -xjf nvidia-persistenced-init.tar.bz2
cd nvidia-persistenced-init/
# 开机启动(install.sh执行两次,第一次可能环境变量生效原因会失败)
./install.sh
./install.sh
......
Checking for systemd requirements...
/usr/lib/systemd/system directory exists? Yes
systemctl found in PATH? Yes
systemd installation/uninstallation supported
Installation parameters:
User : nvidia-persistenced
Group : nvidia-persistenced
systemd service installation path : /usr/lib/systemd/system
Adding user 'nvidia-persistenced' to group 'nvidia-persistenced'... done.
Installing sample systemd service nvidia-persistenced.service... done.
Enabling nvidia-persistenced.service... done.
Starting nvidia-persistenced.service... done.
systemd service successfully installed.
安装 docker
我的镜像已经内置了 docker 环境,所以此步骤非必选
安装 docker(20.10.17)
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce=5:20.10.17~3-0~ubuntu-focal docker-ce-cli=5:20.10.17~3-0~ubuntu-focal containerd.io docker-compose-plugin
安装 nvidia-docker
因为业务需要在容器环境中调用 nvidia 显卡,所以仅仅宿主机调用还不够
安装 nvidia-docker
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) &&
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add - &&
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
apt-get update
# 注意选 NO 再回车,避免覆盖了原配置
apt-get install -y nvidia-docker2 --allow-unauthenticated
如果docker是全新安装的,操作如下:
rm /etc/docker/daemon.json
cat >> /etc/docker/daemon.json << EOF
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
EOF
systemctl daemon-reload && systemctl restart docker
如果之前的操作系统内已经安装好 docker ,并且额外定制了 daemon.json 内容,仅仅追加 nvidia runtime即可,不要覆盖旧内容,例如
# cat /etc/docker/daemon.json
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
},
"insecure-registries": ["10.244.0.0/18","10.244.64.0/18"],
"max-concurrent-downloads": 10,
"live-restore": true,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"bip": "172.17.0.1/16",
"data-root": "/var/lib/docker",
"exec-opts": ["native.cgroupdriver=systemd"],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
# 重启docker
systemctl daemon-reload && systemctl restart docker
测试容器环境是否可调用 nvidia:
# docker run -it --rm --name test --gpus all ubuntu:latest nvidia-smi
Thu Nov 9 10:48:50 2023
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 Tesla T4 On | 00000000:00:0D.0 Off | 0 |
| N/A 28C P8 9W / 70W | 2MiB / 15360MiB | 0% Default |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| No running processes found |
+---------------------------------------------------------------------------------------+
在 Kubernetes 调用 nvidia
安装nvida插件
# 选择合适的版本安装插件,选择合适的一条执行一次即可
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/master/nvidia-device-plugin.yml
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.12.2/nvidia-device-plugin.yml
pod 申请 GPU 资源
# 示例:
apiVersion: v1
kind: Pod
metadata:
name: pod_name
spec:
containers:
- name: cnt_name
resources:
limits:
nvidia.com/gpu: 1 # requesting 1 GPU
总结
生产环境需要保障确定性的变更,所以本文着重强调了两点:
- 使用 运行文件 安装方式,避免驱动发生意外的自动更新。
- 不要覆盖现存 docker 环境中的 daemon.json 配置,全新安装 docker 可忽略。
本文属于专题:Kubernetes
- Ubuntu20.04 安装 nvidia 驱动
- 使用 kubeadm 安装 k8s 集群
- kubectl 配置自动补全